package io.kiki.sba.registry.server.metadata.resource;

import io.kiki.sba.registry.common.model.console.PersistenceData;
import io.kiki.sba.registry.common.model.console.PersistenceDataBuilder;
import io.kiki.sba.registry.common.model.constants.ValueConstants;
import io.kiki.sba.registry.common.model.metaserver.ProvideDataChangeEvent;
import io.kiki.sba.registry.common.model.metaserver.ShutdownSwitch;
import io.kiki.sba.registry.common.model.metaserver.ShutdownSwitch.CauseEnum;
import io.kiki.sba.registry.core.model.Result;
import io.kiki.sba.registry.server.metadata.provide.data.DefaultProvideDataNotifier;
import io.kiki.sba.registry.server.metadata.provide.data.FetchStopPushService;
import io.kiki.sba.registry.server.metadata.provide.data.ProvideDataService;
import io.kiki.sba.registry.server.metadata.resource.filter.LeaderAwareRestController;
import io.kiki.sba.registry.server.shared.resource.AuthChecker;
import io.kiki.sba.registry.store.api.DBResponse;
import io.kiki.sba.registry.store.api.OperationStatus;
import io.kiki.sba.registry.util.JsonUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;
import java.util.Collections;
import java.util.Map;

@Path("shutdown")
@LeaderAwareRestController
public class ShutdownSwitchResource {

    private static final Logger logger = LoggerFactory.getLogger(ShutdownSwitchResource.class);


    @Autowired
    private ProvideDataService provideDataService;

    @Autowired
    private DefaultProvideDataNotifier provideDataNotifier;

    @Autowired
    private FetchStopPushService fetchStopPushService;

    @POST
    @Path("update")
    @Produces(MediaType.APPLICATION_JSON)
    public Result shutdown(@FormParam("shutdown") String shutdown, @FormParam("token") String token) {

        if (!AuthChecker.authCheck(token)) {
            logger.error("update shutdownSwitch, shutdown={} auth check={} fail!", shutdown, token);
            return Result.failed("auth check fail");
        }

        if (!fetchStopPushService.isStopPush()) {
            logger.error("push switch is open");
            return Result.failed("push switch is open");
        }

        ShutdownSwitch shutdownSwitch;
        if (StringUtils.equalsIgnoreCase(shutdown, "true")) {
            shutdownSwitch = new ShutdownSwitch(true, CauseEnum.force.getCause());
        } else {
            shutdownSwitch = new ShutdownSwitch(false);
        }

        String value = JsonUtils.writeValueAsString(shutdownSwitch);
        PersistenceData persistenceData = PersistenceDataBuilder.createPersistenceData(ValueConstants.SHUTDOWN_SWITCH_DATA_ID, value);
        try {
            boolean ret = provideDataService.saveProvideData(persistenceData);
            logger.info("Success update shutdownSwitch:{} to DB result {}!", value, ret);
        } catch (Throwable e) {
            logger.error("Error update shutdownSwitch:{} to DB!", value, e);
            throw new RuntimeException("Update shutdownSwitch to error!", e);
        }

        fireDataChangeNotify(persistenceData.getVersion(), ValueConstants.SHUTDOWN_SWITCH_DATA_ID);

        Result result = new Result();
        result.setSuccess(true);
        return result;
    }

    @GET
    @Path("query")
    @Produces(MediaType.APPLICATION_JSON)
    public Map<String, String> query() {
        DBResponse<PersistenceData> response = provideDataService.queryProvideData(ValueConstants.SHUTDOWN_SWITCH_DATA_ID);
        if (response.getOperationStatus() == OperationStatus.notfound) {
            return Collections.singletonMap("switch", "empty value.");
        }
        PersistenceData entity = response.getEntity();
        return Collections.singletonMap("switch", entity.getData());
    }

    private void fireDataChangeNotify(Long version, String dataInfoId) {

        ProvideDataChangeEvent provideDataChangeEvent = new ProvideDataChangeEvent(dataInfoId, version);
        if (logger.isInfoEnabled()) {
            logger.info("send PERSISTENCE_DATA_CHANGE_NOTIFY_TASK notifyProvideDataChange: {}", provideDataChangeEvent);
        }
        provideDataNotifier.notifyProvideDataChange(provideDataChangeEvent);
    }


    public ShutdownSwitchResource setProvideDataService(ProvideDataService provideDataService) {
        this.provideDataService = provideDataService;
        return this;
    }


    public ShutdownSwitchResource setProvideDataNotifier(DefaultProvideDataNotifier provideDataNotifier) {
        this.provideDataNotifier = provideDataNotifier;
        return this;
    }

    /**
     * Setter method for property <tt>fetchStopPushService</tt>.
     *
     * @param fetchStopPushService value to be assigned to property fetchStopPushService
     * @return ShutdownSwitchResource
     */
    public ShutdownSwitchResource setFetchStopPushService(FetchStopPushService fetchStopPushService) {
        this.fetchStopPushService = fetchStopPushService;
        return this;
    }
}
